// 引入必要的包
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
import * as pb from '../proto/testConditionUiWithPlugin_pb'
import {TestConditionServiceClient} from '../proto/testConditionUiWithPlugin_grpc_pb'
import {DeviceMonitorMsg, MonitorType, MonitorValue} from "../proto/testConditionUiWithPlugin_pb";

const sleep = (n: number) => new Promise((r) => setTimeout(r, n))

/**
 * 将DeviceMonitorMsg转化成Object形式进行访问
 * @param deviceMonitorMsg
 */
function convertDeviceMonitorMsgToObject(deviceMonitorMsg: DeviceMonitorMsg): any {
    // 最终输出
    const result: any = {};
    // 类型设置
    result.type = deviceMonitorMsg.getType();
    // 获得map<string, MonitorValue> values
    const valuesMap = deviceMonitorMsg.getValuesMap();
    // 准备记录
    const valuesObject: any = {};

    valuesMap.forEach((monitorValue: any, key: any) => {
        // 获得每一项(vs1~16/vi/cv)的map<string, UnitValue> values
        const unitValuesMap = monitorValue.getValuesMap();
        // 准备转化结果的容器
        const unitValuesObject: any = {};
        // 进行映射
        unitValuesMap.forEach((unitValue: any, unitKey: any) => {
            unitValuesObject[unitKey] = {
                dvalue0: unitValue.getDvalue0(),
                dvalue1: unitValue.getDvalue1(),
            };
        });

        valuesObject[key] = unitValuesObject;
    });

    result.values = valuesObject;

    return result;
}


class TestConditionGrpcClient {
    // 创建client handle,proto的服务客户端
    client_: TestConditionServiceClient;

    constructor() {
        // 指定连接的目标
        const target = '192.168.52.128:8080';
        // 创建client handle
        this.client_ = new TestConditionServiceClient(target, grpc.credentials.createInsecure())
    }

    // ui询问当前可工作的site有哪些
    checkEnabledSite() {
        // 发送给服务端的空白数据
        const req = new pb.BlankMsg()
        // 向服务端发送信息,使用回调函数处理服务端返回的数据
        this.client_.checkEnabledSite(req, (err, data) => {
            if (err) {
                console.log(err);
            } else {
                console.log(data?.toObject());
            }
        })
    }

    // ui请求从c++插件服务端的信息,接收数据流
    async startGetDeviceMonitorInfo() {
        // 准备需要发送给服务端的数据
        const req = new pb.CheckSite();
        req.setSiteidx(0);
        req.setType(MonitorType.E_ALL)

        // 给服务端发送消息
        const st = this.client_.startGetDeviceMonitorInfo(req)
        // 持续接收服务端的数据
        st.on('data', (d: pb.DeviceMonitorMsg) => {
            // 将 valuesMap 转换为对象
            const data = convertDeviceMonitorMsgToObject(d)
            /* 解析数据,更新到当前页面 */
            /* 解析vs */
            for (let i = 1; i <= 16; ++i) {
                if (data.values[`vs${i}`]) {
                    console.log(`vs${i}`, data.values[`vs${i}`])
                }
            }
            /* 解析vi */
            if (data.values.vi) {
                console.log("vi", data.values.vi)
            }
            /* 解析cv */
            if (data.values.cv) {
                console.log("cv", data.values.cv)
            }
        })

        // 服务端发送完毕
        st.on('end', () => {
            console.log('done')
        })

        // 当服务端状态异常时会报错
        st.on('error', (err: any) => {
            console.log('error', err)
        })
    }
}

const main = async () => {
    const client = new TestConditionGrpcClient()

    client.checkEnabledSite();

    for (let i = 0; i < 10; i++) {
        await client.startGetDeviceMonitorInfo();
        await sleep(3000)
    }
}

main()
